package com.txby.wxyyApi.component.web;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.google.common.collect.Maps;
import com.jck.mybatis.mapper.MybatisBaseDaoCRUD;
import com.jck.tools.ChkUtil;
import com.jck.tools.GetIp;
import com.jck.tools.MD5Util;
import com.jck.tools.SERVER_ERR;
import com.jck.tools.Times;
//import com.jck.tools.component.SpringEhcacheUtil;
import com.jck.tools.component.controller.BaseController;
import com.jck.tools.exception.BusinessException;
import com.jck.tools.exception.ParameterException;
import com.jck.tools.util.FreeMarkers;
import com.txby.wxyyApi.component.util.SpringEhcacheUtil;
import com.txby.wxyyApi.config.PropertySourceConfig;
import com.txby.wxyyApi.data.CommonApiModelMapExt;
import com.txby.wxyyApi.data.CommonMybaitsDataMapExt;
import com.txby.wxyyApi.data.EntityData;
import com.txby.wxyyApi.entity.WrSysApiUser;

public class CommonController extends BaseController {
	@Resource(name = "mybatisBaseDaoCRUD")
	public MybatisBaseDaoCRUD mBaseDao;
	@Resource
	public PropertySourceConfig propertySourceConfig;
	@Resource(name = "springEhcacheUtil")
	public SpringEhcacheUtil springEhcacheUtil;

	public String apiTokenCachName = "apiTokenCache";// 缓存名称
	private HttpServletRequest request;
	private HttpServletResponse response;

	public boolean isTokenValid;// 是否token有效
	public static String apiUserId = "";// 用户id
	public String userToken = "";// 当前token
	public String reParamType = "";// 当前请求类型（须）0：web,1:app

	public String clientIP = "";// 当前IP
	public String requestMethod = "";// 当前请求方法
	public  String tempTableName = "";// in查询时超过1000创建的临时表名
	public  boolean isGlobaltempTable=true;//是全局（所有会话）还是本地（当前会话）
	private static Logger logger = LoggerFactory.getLogger(CommonController.class);
	
	@Override
	public String exp(HttpServletRequest request, Exception ex, HttpServletResponse res) {
		res.setCharacterEncoding("UTF-8");
		request.setAttribute("ex", ex);
		res.getStatus();
	 
		if (ex instanceof BusinessException) {
			logger.error(ex.getMessage(), ex);
			return "error/500";
		} else if (ex instanceof ParameterException) {
			logger.error(ex.getMessage(), ex);
			return "error/404";
		} else {
			return "{\"code\":\"1\",\"info\":\"请求异常\",\"msg\":\"请求异常\"}";
//			logger.error(ex.getMessage(), ex); // return "error/error"; 
//			return "tttttt";
			
			/* Map m = new HashMap(); m.put("code", "1"); m.put("info", "请求异常");
			  m.put("msg", "请求异常"); 
			  return JSON.toJSONString(m);*/
//			  return ResponseUtils.toJSONString(m);
			 
		}
		// return super.exp(request, ex, res);
	}

	/**
	 * 上传单文件（文件name参数名file）,按日期hh:mmss:sss命名 code 4017: 上传出现异常 4018:
	 * 上传文件大小受限制（不能超过2M） 4019:文件格式受限制（支持gif、png、jpg、bmp）
	 * 
	 * @param request
	 * @param savePath
	 * @return
	 */
	@Override
	public Map fileUpload(HttpServletRequest request, String savePath) {
		Map m = new HashMap();
		m.put("code", "4017");
		m.put("info", "上传出现异常");
		m.put("msg", "上传失败");
		m.put("url", "");
		try {
			Date date = new Date();
			String newName = Times.getDateToStringHHmmssSSS(date);// 自定义文件名字
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
			CommonsMultipartFile orginalFile = (CommonsMultipartFile) multipartRequest
					.getFile("tradingCertificatePicFile");// 表单中对应的文件名；
			if (orginalFile != null && !orginalFile.isEmpty()) {
				String fileName = orginalFile.getOriginalFilename();
				String suffix = fileName.substring(fileName.indexOf("."));// 获得后缀名

				long size = orginalFile.getSize();
				/*
				 * if(orginalFile.getSize()>6024*2000){ m.put("code", "4018");
				 * m.put("info","图片上传文件大小受限制（不能超过2M）"); m.put("msg",
				 * "图片不能大于2M"); return m; }
				 */

				if (!suffix.equals(".bmp") && !suffix.equals(".gif") && !suffix.equals(".png")
						&& !suffix.equals(".jpg")) {
					m.put("code", "4019");
					m.put("info", "文件格式受限制（支持gif、png、jpg、bmp）");
					m.put("msg", "上传格式应为gif、png、jpg、bmp");
					return m;
				}
				fileName = newName + suffix;
				File file = new File(savePath);
				if (!file.exists()) {// 判断文件夹是否存在，不存在就根据上面的路径创建文件夹
					file.mkdirs();
				}
				String realpath = request.getSession().getServletContext().getRealPath(savePath);// 给予存储路径
				File f = new File(realpath + File.separator + fileName);
				String url = savePath + fileName;// 获得相对路径
				FileUtils.copyInputStreamToFile(orginalFile.getInputStream(), f);// 获取文件，并按照路径保存
				m.put("code", "0");
				m.put("info", "上传成功");
				m.put("msg", "上传成功");
				m.put("url", url);
				m.put("date", date);
				return m;
			}

		} catch (Exception e) {
			e.printStackTrace();

			return m;
		}

		return m;
	}

	/**
	 * 根据用户名称
	 * 
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param userData
	 * @return
	 */
	public String getCreateTokenByGzz01ApiUser(WrSysApiUser userData) {
		String userName = userData.getId() + ",";
		String verifyCode = MD5Util.getMD5ofStr(userName + userData.getPassWord() + new Date().getTime(), 2);
		String token = userName + verifyCode;
		return token;
	}

	public Map getCreateTokenByGzz01ApiUserAndPutCache(WrSysApiUser userData) {
		String uid = userData.getId();
		
		String verifyCode = MD5Util.getMD5ofStr(uid + userData.getPassWord() + new Date().getTime(), 2);
		String token = uid + "," + verifyCode;
		putTokenCache(uid + "_token", token);
		Map info = writeReturnJson(SERVER_ERR.CODE_0.getCode(), "token正常", "token正常");
		info.put("token", token);
		return info;
	}

	public CommonApiModelMapExt chekTokenCahceValid(String token, String type){
		List oldTypeList = Arrays.asList("web", "app");// (“0”:web,”1”:app)
		if (ChkUtil.isEmpty(token) || ChkUtil.isEmpty(type) || (!oldTypeList.contains(type.toLowerCase()))) {
			isTokenValid = false;
			apiUserId = "";// 用户id
			userToken = "";// 当前token
			reParamType = "";// 当前请求类型（须）0：web,1:app
			return writeReturnJson(SERVER_ERR.CODE_1.getCode(), "验证失败,参数不正确", "验证失败,参数不正确");
		}else {
			try {
				String[] data = token.split(",");
				if (data.length < 2) {
					isTokenValid = false;
					apiUserId = "";// 用户id
					userToken = "";// 当前token
					reParamType = "";// 当前请求类型（须）0：web,1:app
					return writeReturnJson(SERVER_ERR.CODE_1.getCode(), "验证失败,token格式不正确", "验证失败,token格式不正确");
				}else{
					apiUserId = data[0];// 用户id
					String oldtoken = (String) springEhcacheUtil.get(apiTokenCachName, apiUserId + "_token");
					if (ChkUtil.isEmpty(oldtoken)) {
						isTokenValid = false;
						apiUserId = "";// 用户id
						userToken = "";// 当前token
						reParamType = "";// 当前请求类型（须）0：web,1:app
						return writeReturnJson(SERVER_ERR.CODE_1.getCode(), "验证失效,请重新登录", "验证失效,请重新登录");
					}
					
					if (!oldtoken.equals(token)) {
						isTokenValid = false;
						apiUserId = "";// 用户id
						userToken = "";// 当前token
						reParamType = "";// 当前请求类型（须）0：web,1:app
						return writeReturnJson(SERVER_ERR.CODE_1.getCode(), "用户已在其他设备登录,请重新登录", "用户已在其他设备登录,请重新登录");
					} else{
						isTokenValid = true;
						apiUserId = data[0];// 用户id
						userToken = token;// 当前token
						reParamType = type;// 当前请求类型（须）0：web,1:app
						this.springEhcacheUtil.put(apiTokenCachName, apiUserId + "_token", token);
						return writeReturnJson(SERVER_ERR.CODE_0.getCode(), "token正常", "token正常");
					}
				}
			} catch (Exception e) {
				isTokenValid = false;
				apiUserId = "";// 用户id
				userToken = "";// 当前token
				reParamType = "";// 当前请求类型（须）0：web,1:app
				e.printStackTrace();
				saveLog("传入的token异常，可能格式不正确");
				return writeReturnJson(SERVER_ERR.CODE_1.getCode(), "token异常", "token异常");
			}
			
		}

	}

	public Map tokenNotValid(CommonApiModelMapExt map) throws IOException {
		if (!this.isTokenValid) {
			map.clear();
			map = new CommonApiModelMapExt(SERVER_ERR.CODE_1.getCode(), "token异常", "token异常");
		} else {
			map = new CommonApiModelMapExt(SERVER_ERR.CODE_0.getCode(), "token正常", "token正常");
		}
		return map;
	}

	/**
	 * 返回要写入客户端的错误代码和信息
	 * 
	 * @param codeFlag
	 *            错码标识
	 * @param infoMessage
	 * @throws IOException
	 */
	public CommonApiModelMapExt writeReturnJson(String codeFlag, String info, String msg) {
		CommonApiModelMapExt mm = new CommonApiModelMapExt(codeFlag, info, msg);
		return mm;
	}

	/**
	 * 存放token缓存，默认token,存活1小时，间隔1小时内有效
	 * 
	 * @param key
	 * @param value
	 */
	/*
	 * public void putTokenCache(String key,String value){
	 * this.springEhcacheUtil.put(apiTokenCachName, key, value); }
	 */
	private void putTokenCache(String key, String value) {
		this.springEhcacheUtil.put(apiTokenCachName, key, value);
	}

	/**
	 * 用户手动日志保存(格式)
	 * 
	 * @param message
	 */
	public void saveLog(String message) {
		if (isTokenValid) {
			logger.warn("触发时间：" + Times.getTimes() + "，IP:" + clientIP + ",请求参数类型" + reParamType + ",请求方法类型"
					+ requestMethod + ",用户：" + apiUserId + "" + "，信息说明：" + message + "");
		} else {
			logger.warn("触发时间：" + Times.getTimes() + "，IP:" + clientIP + ",请求参数类型" + reParamType + ",请求方法类型"
					+ requestMethod + "，信息说明：" + message + "");
		}
	}

	/**
	 * 先执行此处
	 * 
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param token
	 * @param type
	 * @param request
	 */
	@ModelAttribute
	public void initModelAttribute(HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;
		this.requestMethod = request.getMethod().toUpperCase();
		try {
			this.clientIP = GetIp.getIpAddr(request);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	/**
	 * @Description:sql in条件查询拆分
	 * @param sqlId
	 * @return
	 */
	public static String getSplitInSql(String[] sqlId) {
		String sql = "";
		for (String str : sqlId) {
			sql += "'" + str + "',";
		}
		if (!ChkUtil.isEmpty(sql)) {
			sql = sql.substring(0, sql.length() - 1);
		}
		return sql;
	}

	/**
	 * @Description: sql in条件查询拆分
	 * @param sqlId
	 * @return
	 */
	public static String getSplitInSql(Set<String> sqlId) {
		String sql = "";
		for (String str : sqlId) {
			sql += "'" + str + "',";
		}
		if (!ChkUtil.isEmpty(sql)) {
			sql = sql.substring(0, sql.length() - 1);
		}
		return sql;
	}

	/**
	 * @Description: 保存数据表中，外键id的“，”分割的拆分
	 * @param sqlId
	 * @return
	 */
	public static String getSplitNewString(String[] sqlId) {
		String sql = "";
		for (String str : sqlId) {
			sql += str + ",";
		}
		if (!ChkUtil.isEmpty(sql)) {
			sql = sql.substring(0, sql.length() - 1);
		}
		return sql;
	}

	/**
	 * @Description: 保存数据表中，外键id的“，”分割的拆分
	 * @param sqlId
	 * @return
	 */
	public static String getSplitNewString(Set<String> sqlId) {
		String sql = "";
		for (String str : sqlId) {
			sql += str + ",";
		}
		if (!ChkUtil.isEmpty(sql)) {
			sql = sql.substring(0, sql.length() - 1);
		}
		return sql;
	}
	/**
	 * 根据传入的含","的字符串ids 如8a8ac49f5ad9d83e015ad9f98c0b0003,8a8ac49f5ad9fbaf015ada001cb90001
	 * 及查询字段条件返回带where或带and 的sql条件语句
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param ids  如8a8ac49f5ad9d83e015ad9f98c0b0003,8a8ac49f5ad9fbaf015ada001cb90001
	 * @param fieldName 如查询字段t.name
	 * @return
	 */
	public  CommonMybaitsDataMapExt getSplitInSqlByMapData(String ids,String fieldName,String tempTableName) {
		if(ChkUtil.isEmpty(fieldName)||ChkUtil.isEmpty(ids)){
			return null;
		}
		return  getSplitInSqlByMapData(ids.split(","), fieldName,tempTableName);
	}
	/**
	 * 根据传入的字符串ids数组 如8a8ac49f5ad9d83e015ad9f98c0b0003,8a8ac49f5ad9fbaf015ada001cb90001
	 * 及查询字段条件返回带where或带and 的sql条件语句
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param ids  如8a8ac49f5ad9d83e015ad9f98c0b0003,8a8ac49f5ad9fbaf015ada001cb90001
	 * @param fieldName 如查询字段t.name
	 * @return
	 */
	public  CommonMybaitsDataMapExt getSplitInSqlByMapData(String[] ids,String fieldName,String tempTableName) {
		String inSql="";
		if(ChkUtil.isEmpty(fieldName)||ids==null||ids.length==0){
			return null;
		}
		Set<String> setData=new HashSet<>(Arrays.asList(ids));
		Map  pojoMap=new HashMap();
		int i = 0;  
		for(String id:setData){
			pojoMap.put(id, id);
			if(i++ != 0)   inSql+=",";
			inSql+="#{"+CommonMybaitsDataMapExt.POJO_PREFIX+id+"}";
		}
		String inSqlByWhere=inSql.equals("")?"":" where "+fieldName+" in("+inSql+") ";
		String inSqlByAnd=inSql.equals("")?"":" and  "+fieldName+" in("+inSql+") ";
		if(setData.size()>=1000){
			tempTableName=getUniqueTempTableName(tempTableName);
			this.tempTableName=tempTableName;
			// 定义模板变量
			Map<String, Object> model = Maps.newHashMap();
			List<EntityData> entityData=new ArrayList(){{
				add(new EntityData());
			}};
			model.put("entityData", entityData);
			model.put("tableName", tempTableName);
			model.put("ids", new ArrayList<>(setData));
			String executeSql=FreeMarkers.getFtlData(model, "createTable.ftl");
			mBaseDao.executeSql(executeSql, null);
			inSqlByWhere=inSql.equals("")?"":" ,"+tempTableName+" where "+fieldName+"="+tempTableName+".id ";
			inSqlByAnd="";
		}
		return new CommonMybaitsDataMapExt(inSqlByWhere, inSqlByAnd, pojoMap);
	}
	/**
	 * 根据传入的字符串ids集合对象 如Set,List
	 * 及查询字段条件返回带where或带and 的sql条件语句
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param ids  如8a8ac49f5ad9d83e015ad9f98c0b0003,8a8ac49f5ad9fbaf015ada001cb90001
	 * @param fieldName 如查询字段t.name
	 * @return
	 */
	public  CommonMybaitsDataMapExt getSplitInSqlByMapData(Collection<? extends String>  ids,String fieldName,String tempTableName) {
		String inSql="";
		if(ChkUtil.isEmpty(fieldName)||ids==null||ids.size()==0){
			return null;
		}
		Set<String> setData=new HashSet<>(ids);
		Map  pojoMap=new HashMap();
		int i = 0;  
		for(String id:setData){
			pojoMap.put(id, id);
			if(i++ != 0)   inSql+=",";
			inSql+="#{"+CommonMybaitsDataMapExt.POJO_PREFIX+id+"}";
		}
		String inSqlByWhere=inSql.equals("")?"":" where "+fieldName+" in("+inSql+") ";
		String inSqlByAnd=inSql.equals("")?"":" and  "+fieldName+" in("+inSql+") ";
		if(setData.size()>=1000&&!ChkUtil.isEmpty(tempTableName)){
			tempTableName=getUniqueTempTableName(tempTableName);
			this.tempTableName=tempTableName;
			// 定义模板变量
			Map<String, Object> model = Maps.newHashMap();
			List<EntityData> entityData=new ArrayList(){{
				add(new EntityData());
			}};
			model.put("entityData", entityData);
			model.put("tableName", tempTableName);
			model.put("ids", new ArrayList<>(setData));
			String executeSql=FreeMarkers.getFtlData(model, "createTable.ftl");
			mBaseDao.executeSql(executeSql, null);
			inSqlByWhere=inSql.equals("")?"":" ,"+tempTableName+" where "+fieldName+"="+tempTableName+".id ";
			inSqlByAnd="";
		}
		return new CommonMybaitsDataMapExt(inSqlByWhere, inSqlByAnd, pojoMap);
	}
	
	/**
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param tempTableName
	 * @return
	 */
	public  String  getUniqueTempTableName(String tempTableName){
		String pre=isGlobaltempTable?"##temp_":"#temp_";
		String suf=""+new Date().getTime();
		tempTableName=tempTableName==null?pre+suf:pre+tempTableName+suf;
		return tempTableName;
	}
	
	

}
